﻿using System;
using System.Collections.Generic;
using System.Threading;
using Cubicle.Excel.Binding;

namespace Cubicle.Examples
{
    public class InvokeUnitTestClass
    {

        #region Static Fields

        private static Random _rnd = new Random();
        public static int SomeStaticField1 = 20;
        public static int[] SomeStaticField2 = new [] {9,8,7};
        public static List<string> SomeStaticField3 = new List<string> { "twintig", "een-en-twintig", "twee-en-twintig"};

        #endregion

        #region Static Constructor

        static InvokeUnitTestClass()
        {
            SomeStaticProperty1 = 1;
            SomeStaticProperty2 = new[] {1,2,3};
            SomeStaticProperty3 = new List<int>();
            SomeStaticProperty3.AddRange(SomeStaticProperty2);
        }

        #endregion

        #region Static Properties

        public static int SomeStaticProperty1 { get; set; }
        public static int[] SomeStaticProperty2 { get; set; }
        public static List<int> SomeStaticProperty3 { get; set; }


        #endregion

        #region Virtual fields

        public int SomeVirtualField1 = 3;
        public int[] SomeVirtualField2 = new int[] { 1, 2, 3 };
        public List<string> SomeVirtualField3 = new List<string>() {"1", "2", "3"};

        #endregion

        #region Constructors

        public InvokeUnitTestClass() { }

        public InvokeUnitTestClass(string a)
        {
            SomeVirtualField3[0] = a;
        }

        public InvokeUnitTestClass(int a)
        {
            SomeVirtualField1 = a;
        }

        public InvokeUnitTestClass(string a, int b) { }

        public InvokeUnitTestClass(object a, int[] b) { }

        #endregion

        #region Virtual properties

        public List<string> SomeVirtualProperty3
        {
            get { return SomeVirtualField3; }
            set { SomeVirtualField3 = value;  }
        }

        public int SomeVirtualProperty1
        {
            get { return SomeVirtualField1; }
            set { SomeVirtualField1 = value; }
        }

        #endregion

        #region Indexer

        public string this[int i]
        {
            get
            {
                return SomeVirtualField3[i];
            }
            set
            {
                SomeVirtualField3[i] = value;
            }
        }

        #endregion

        #region Static Methods

        public static void testStatic1() { }
        public static object testStatic2()
        {
            return 20;
        }

        public static string testStatic3(byte a, long b)
        {
            return "Static";
        }

        public static string testStatic4(byte a, long b)
        {
            return "Static Overload";
        }

        public static string testStatic4(long a, byte b)
        {
            return "Static Overload";
        }

        #endregion

        #region Virtual Methods

        public void test1() {}

        public object test2()
        {
            return 20;
        }

        #region Overloaded Methods

        public string test3(byte a, long b)
        {
            return "Overload 0";
        }

        public string test3(long a, byte b)
        {
            return "Overload 1";
        }

        #endregion

        public object[,] test4(object a, object b)
        {
            var result = new object[13,2];
            result[0, 1] ="parameter 1";   result[0, 1] = a;
            result[1, 1] ="parameter 2";   result[1, 1] = b;
            result[2, 1] ="bool";   result[2, 1] = true;
            result[3, 1] ="byte";   result[3, 1] = byte.MaxValue;
            result[4, 1] ="short";   result[4, 1] = short.MaxValue;
            result[5, 1] ="int";   result[5, 1] = int.MaxValue;
            result[6, 1] ="long";   result[6, 1] = long.MaxValue;
            result[7, 1] ="float";   result[7, 1] = float.MaxValue;
            result[8, 1] ="double";   result[8, 1] = double.MaxValue;
            result[9, 1] ="datetime";   result[9, 1] = DateTime.Now;
            result[10, 1] ="char";  result[10, 1] = 'x';
            result[11, 1] ="string";  result[11, 1] = "String";
            result[12, 1] ="decimal";  result[12, 1] = decimal.MaxValue;
            return result;
        }

        public object test5(object[] a, object b)
        {
            return a;
        }

        public object test6(byte[] a, long[] b)
        {
            return a;
        }

        public static object test7(object a, object b)
        {
            return a;
        }

        #region Generics

        public object test8<T, S>(object a, object b)
        {
            return a;
        }

        #endregion

        #region Overloaded generics

        public object test9<T, S>(T a, S b)
        {
            return a;
        }

        public object test9<T>(T a, T b)
        {
            return a;
        }

        #endregion

        #region Double array parameters

        public object test10(long[,] a, byte[,] b)
        {
            return a;
        }

        #endregion

        #region Jagged array parameters

        public object test11(long[][] a, byte[,] b)
        {
            return a;
        }

        #endregion

        #endregion

        [Binding(IsAsync = true)]
        public static string AsyncTest()
        {
            Thread.Sleep(2000);
            return "Boom";
        }

        [Binding(IsAsync = false)]
        public static string SyncTest()
        {
            Thread.Sleep(2000);
            return "Boom";
        }

        public DateTime WhatIsTheTime()
        {
            return DateTime.Now;
        }

        public Double GimmeANumber()
        {
            return _rnd.NextDouble();
        }
    }
}
